package Model;

import java.nio.ByteBuffer;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class Mix {

	private String m_Address;
	private Integer m_Port;
	private String m_Key;
	byte[] uuid;
	 private Cipher cipher;
	
	public Mix(String address, String port, String key) {
		m_Address = address;
		m_Port = Integer.parseInt(port);
		m_Key = key;
			
		uuid = java.util.UUID.randomUUID().toString().getBytes();
		
		
		try 
		{	         
	         // Create key and cipher
	         Key aesKey = new SecretKeySpec(m_Key.getBytes(), "AES");
	         cipher = Cipher.getInstance("AES");
	         
	         // encrypt the text
	         cipher.init(Cipher.ENCRYPT_MODE, aesKey);	           
		}
        catch (Exception e) {
            System.out.println("Invalid Key:" + e.getMessage());
            return;
        }

	}

	public byte[] encrypt(byte[] b, String nextAddress, Integer nextPort) {
		
		try 
		{
			byte[] address = nextAddress.getBytes();
			byte[] port = ByteBuffer.allocate(4).putInt(nextPort).array();
			byte[] len = new byte[1];
			len[0] = (byte)address.length;
			
			byte[] uuidLen = new byte[1];
			uuidLen[0] = (byte)uuid.length;
			
			
			return cipher.doFinal(arraysConcatenation(len, address, port, uuidLen, uuid, b));	         			  
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	  
		return null;
	}
	
	public byte[] encrypt(byte[] b) {
		
		try 
		{
			return cipher.doFinal(b);	         			  
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	  
		return null;
	}
	
	private byte[] arraysConcatenation(Object... arrays)
	{
		int size = 0;
		for (int i = 0; i < arrays.length; i++) 
		{
			size += ((byte[])arrays[i]).length;
		}
		
		byte[] array = new byte[size];
		
		int counter = 0;
		for (int i = 0; i < arrays.length; i++) 
		{
			System.arraycopy(arrays[i], 0, array, counter, ((byte[])arrays[i]).length);
			counter += ((byte[])arrays[i]).length;
		}		
		
		return array;
	}

	public String getAddress() {
		return m_Address;
	}

	public Integer getPort() {
		return m_Port;
	}

}
